<?php
/***************************************************************
*  Copyright notice
*  
*  (c) 2005 - 2006 Ingo Schmitt <is@marketing-factory.de>
*  All rights reserved
*
*  This script is part of the Typo3 project. The Typo3 project is 
*  free software; you can redistribute it and/or modify
*  it under the terms of the GNU General Public License as published by
*  the Free Software Foundation; either version 2 of the License, or
*  (at your option) any later version.
* 
*  The GNU General Public License can be found at
*  http://www.gnu.org/copyleft/gpl.html.
* 
*  This script is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU General Public License for more details.
*
*  This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/
/** 
 * Plugin 'checkout' for the 'commerce' extension.
 *
 * @author	Thomas Hempel <thomas@work.de>
 * @author	Ingo Schmitt <is@marketing-factory.de>

 * @todo Cleanup Templates Mails and html
 * @todo has to be rewritten completly
 * 
 * $Id: class.tx_commerce_pi5.php 308 2006-07-26 22:23:51Z ingo $
 */
die(' user pi3');
require_once(PATH_tslib."class.tslib_pibase.php");

/**
 * tx_commerce includes
 */
require_once(t3lib_extmgm::extPath('commerce').'lib/class.tx_commerce_product.php');
require_once(t3lib_extmgm::extPath('commerce').'lib/class.tx_commerce_category.php');
require_once(t3lib_extmgm::extPath('graytree').'lib/class.tx_graytree_folder_db.php');
require_once(t3lib_extmgm::extPath('commerce').'lib/class.tx_commerce_pibase.php');
require_once(t3lib_extmgm::extPath('commerce').'pi4/class.tx_commerce_pi4.php');

class tx_commerce_pi5 extends tx_commerce_pibase {
	var $prefixId = "tx_commerce_pi5";				// Same as class name
	var $scriptRelPath = "pi5/class.tx_commerce_pi5.php";	// Path to this script relative to the extension dir.
	var $extKey = "commerce";					// The extension key.
	var $imgFolder = "";
	
	var $templateCode = '';
	var $dbFieldData = array();
	var $formError = array();
	
	/**
	 * Order ID of the Order
	 * Is generated by HOOK generateOrderId if aviailiabe, otherwise is generated by uniqid
	 * @see finisit()
	 * @access public
	 * @var 	string	$OrderID
	 */
	var $orderId;
	
	var $currency = '';
	
	
	/**
	 * If set the Mails will also be written als Output to the Screen
	 * 
	 */
	//var $debugMail= true;
	
	/**
	 * Init Method, autmatically called $this->main
	 * @param 	string	$conf	TypoConfiguration
	 */
	function init($conf){
	    
	    parent::init($conf);
	    $this->conf = $conf;
		$this->pi_setPiVarDefaults();
		$this->pi_loadLL();
		$this->imgFolder = "uploads/tx_commerce/";
	  
	   
		
		if ($this->conf['currency']>'')
		{
			$this->currency = $this->conf['currency'];	
		}
		if (empty($this->currency)) {
			$this->currency = 'EUR';	
		}
		
	}
	
	/**
	 * 
	 * Main Method, automatically called by TYPO3 wher inserting the plugin
	 * @param 	string	$content from Parent Page
	 * @param 	array	$conf	TS-Configuration
	 * @return	string	HTML-Content
	 */
	
	function main($content, $conf)	{
		global $TYPO3_CONF_VARS;
		
		$this->init($conf);
		$GLOBALS['TSFE']->set_no_cache();
		
		/**
		* Return if checkout is not allowed. Currently the method always returns TRUE right now.
		* Some functionality has to be implemented in future.
		*/
		if (!$this->canMakeCheckout())	return 'Checkout is not possible';
	
		// write the billing address into session, if it is present in the REQUEST
		if (isset($this->piVars['billing']))	$GLOBALS['TSFE']->fe_user->setKey('ses', 'billing', $this->piVars['billing']);
		if (isset($this->piVars['delivery']))	$GLOBALS['TSFE']->fe_user->setKey('ses', 'delivery', $this->piVars['delivery']);
		if (isset($this->piVars['payment'])) 	$GLOBALS['TSFE']->fe_user->setKey('ses', 'payment', $this->piVars['payment']);
		
			// fetch the address data from hidden fields if the address_id is set what means that
			// the address was selected from list with radio buttons.
		if (isset($this->piVars['address_uid']))	{
			$GLOBALS['TSFE']->fe_user->setKey('ses', $this->piVars['check'], $this->piVars[$this->piVars['address_uid']]);
		}
		
		$this->MYSESSION['billing'] = $GLOBALS['TSFE']->fe_user->getKey('ses', 'billing');
		$this->MYSESSION['delivery'] = $GLOBALS['TSFE']->fe_user->getKey('ses', 'delivery');
		$this->MYSESSION['payment'] = $GLOBALS['TSFE']->fe_user->getKey('ses', 'payment');
		$this->MYSESSION['mails'] = $GLOBALS['TSFE']->fe_user->getKey('ses', 'mails');

		// get the template
		$this->templateCode = $this->cObj->fileResource($this->conf['templateFile']);
		#debug($GLOBALS['TSFE']->fe_user->tx_commerce_basket,$this->piVars['step']);
		// define the currency
		if ($this->conf['curency']>'')	{
			$this->currency = $this->conf['curency'];	
		}
		
		#print ($this->piVars['step']);
		$paymentType = $this->getPaymentType();
		$sysConfig = $GLOBALS['TYPO3_CONF_VARS']['EXTCONF'][$this->extKey]['SYSPRODUCTS']['PAYMENT'];
		$config = $sysConfig['types'][strtolower((string)$paymentType)];
		if (!isset($config['class']) || !file_exists($config['path'])) die ('No payment possible because I don\'t know how to handle it!');
		require_once($config['path']);
		$paymentObj = t3lib_div::makeInstance($config['class']);
		if (method_exists($paymentObj, 'setStep')) {
			$this->piVars['step'] = $paymentObj->setStep($_REQUEST, $this->piVars['step']);
		}
		
		switch (strtolower($this->piVars['step']))	{
			case 'delivery':
				// get delivery address
				$content = $this->getDeliveryAddress();
				break;
			case 'payment':
				$content = $this->handlePayment();

				// only break at this point if we need some payment handling
				// otherwise go on to the next step
				if ($content != false) break;
			case 'finish':
				$content = $this->finishIt();
				break;
			case 'listing':
				$content = $this->getListing();
				break;
			default:
				// get billing address
				$content = $this->getBillingAddress();
		}
		
		return $this->pi_WrapInBaseClass($content);
	}
	
	/** STEP ROUTINES **/
	
	/**
	 * Creates a form for collection the billing address data.
	 */
	function getBillingAddress($withTitle = 1)	{
		$template = $this->cObj->getSubpart($this->templateCode, '###ADDRESS_CONTAINER###');
		
		$markerArray['###ADDRESS_TITLE###'] = '';
		$markerArray['###ADDRESS_DESCRIPTION###'] = '';
			
		if ($withTitle == 1)	{
			// fill some standard markers
			$markerArray['###ADDRESS_TITLE###'] = $this->pi_getLL('billing_title');
			$markerArray['###ADDRESS_DESCRIPTION###'] = $this->pi_getLL('billing_description');
		}
		
		// get the form
		$billingForm = '<form name="addressForm" action="" method="post">';
		
			// if a user is logged in, get the form from the address management
		if ($GLOBALS['TSFE']->fe_user->user != false)	{
				// make an instance of pi4 (address management)
			$addressMgm = t3lib_div::makeInstance('tx_commerce_pi4');

			$addressMgm->cObj = $this->cObj;
			$addressMgm->templateCode = $this->templateCode;
			
			$amConf = $this->conf;
			$amConf['formFields.'] = $this->conf['billing.']['sourceFields.'];
			$amConf['addressPid'] = $this->conf['address_pid'];
			
			$addressMgm->init($amConf, false);
			$addressMgm->addresses = $addressMgm->getAddresses($GLOBALS['TSFE']->fe_user->user['uid'], $this->conf['billing.']['addressType']);

			$addressMgm->piVars['backpid'] = $GLOBALS['TSFE']->id;

			$billingForm .= $addressMgm->getListing($this->conf['billing.']['addressType'], true, $this->prefixId);
		} else {
			$billingForm .= $this->getInputForm($this->conf['billing.'], 'billing');
		}
		
		$billingForm .= '<input type="radio" name="'.$this->prefixId.'[step]" value="delivery" />' .$this->pi_getLL('billing_deliveryaddress');
		$billingForm .= '<input type="radio" name="'.$this->prefixId.'[step]" value="payment" />' .$this->pi_getLL('billing_nodeliveryaddress');
		$billingForm .= '<input type="hidden" name="'.$this->prefixId.'[check]" value="billing" />';
		
		$markerArray['###ADDRESS_FORM_FIELDS###'] = $billingForm;
		$markerArray['###ADDRESS_FORM_SUBMIT###'] = '<input type="submit" value="' .$this->pi_getLL('billing_submit') .'" /></form>';
		$markerArray['###ADDRESS_DISCLAIMER###'] = $this->pi_getLL('general_disclaimer');
		
		
		/**
		 * Hook for processing Marker Array
		 * Inspired by tt_news
		 * @since 21.01.2006
		 * 
		 */
		$hookObjectsArr = array();
		if (is_array ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['commerce/pi5/class.tx_commerce_pi5.php']['getBillingAddress'])) {
			foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['commerce/pi5/class.tx_commerce_pi5.php']['getBillingAddress'] as $classRef) {
					$hookObjectsArr[] = &t3lib_div::getUserObj($classRef);
			}
		}
		foreach($hookObjectsArr as $hookObj)	{
			if (method_exists($hookObj, 'ProcessMarker')) {
				$markerArray=$hookObj->ProcessMarker($markerArray,$this);
			}
		}
		
		
		
		return $this->cObj->substituteMarkerArray($template, $markerArray);
	}
	
	/**
	 * Creates a form for collection the delivery address data.
	 */
	function getDeliveryAddress() {
		if (!$this->validateAddress('billing')) return $this->getBillingAddress();
		
		$template = $this->cObj->getSubpart($this->templateCode, '###ADDRESS_CONTAINER###');
		
		// fill some standard markers
		$markerArray['###ADDRESS_TITLE###'] = $this->pi_getLL('delivery_title');
		$markerArray['###ADDRESS_DESCRIPTION###'] = $this->pi_getLL('delivery_description');
		
		// get the form
		$deliveryForm = '<form name="addressForm" action="" method="post">';
		$deliveryForm .= '<input type="hidden" name="'.$this->prefixId.'[step]" value="payment" />';
		$deliveryForm .= '<input type="hidden" name="'.$this->prefixId.'[check]" value="delivery" />';

		// if a user is logged in, get the form from the address management
		if (!empty($GLOBALS['TSFE']->fe_user->user)) {
			// make an instance of pi4 (address management)
			$addressMgm = t3lib_div::makeInstance('tx_commerce_pi4');
			$addressMgm->cObj = $this->cObj;
			$addressMgm->templateCode = $this->templateCode;
			
			$amConf = $this->conf;
			$amConf['formFields.'] = $this->conf['delivery.']['sourceFields.'];
			$amConf['addressPid'] = $this->conf['address_pid'];
			
			$addressMgm->init($amConf, false);
			$addressMgm->addresses = $addressMgm->getAddresses($GLOBALS['TSFE']->fe_user->user['uid'], $this->conf['delivery.']['addressType']);

			$addressMgm->piVars['backpid'] = $GLOBALS['TSFE']->id;
			
			$deliveryForm .= $addressMgm->getListing($this->conf['delivery.']['addressType'], true, $this->prefixId);
		} else {
			$deliveryForm .= $this->getInputForm($this->conf['delivery.'], 'delivery');
		}

		$markerArray['###ADDRESS_FORM_FIELDS###'] = $deliveryForm;
		$markerArray['###ADDRESS_FORM_SUBMIT###'] = '<input type="submit" value="' .$this->pi_getLL('delivery_submit') .'" /></form>';
		$markerArray['###ADDRESS_DISCLAIMER###'] = $this->pi_getLL('general_disclaimer');
		
		/**
		 * Hook for processing Marker Array
		 * Inspired by tt_news
		 * @since 21.01.2006
		 * 
		 */
		$hookObjectsArr = array();
		if (is_array ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['commerce/pi5/class.tx_commerce_pi5.php']['getDeliveryAddress'])) {
			foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['commerce/pi5/class.tx_commerce_pi5.php']['getDeliveryAddress'] as $classRef) {
					$hookObjectsArr[] = &t3lib_div::getUserObj($classRef);
			}
		}
		foreach($hookObjectsArr as $hookObj)	{
			if (method_exists($hookObj, 'ProcessMarker')) {
				$markerArray=$hookObj->ProcessMarker($markerArray,$this);
			}
		}
		
		return $this->cObj->substituteMarkerArray($template, $markerArray);
	}
	
	/**
	 * This method handles all the stuff concerning the payment.
	 *
	 */
	function handlePayment() {
		if (!$this->validateAddress('delivery')) return $this->getDeliveryAddress();
		if (!$this->validateAddress('billing')) return $this->getBillingAddress();
		
		
		$sysConfig = $GLOBALS['TYPO3_CONF_VARS']['EXTCONF'][$this->extKey]['SYSPRODUCTS']['PAYMENT'];
		
		// currently set the payment type to fixed value for DEVELOPEMENT
		$paymentType = $this->getPaymentType();
		
		$template = $this->cObj->getSubpart($this->templateCode, '###PAYMENT###');
		
		// fill some standard markers
		$markerArray['###PAYMENT_TITLE###'] = $this->pi_getLL('payment_title');
		$markerArray['###PAYMENT_DESCRIPTION###'] = $this->pi_getLL('payment_description');
		$markerArray['###PAYMENT_DISCLAIMER###'] = $this->pi_getLL('general_disclaimer') .'<br />' .$this->pi_getLL('payment_disclaimer');;
		
		
		$config = $sysConfig['types'][strtolower((string)$paymentType)];
				
		if (!isset($config['class']) || !file_exists($config['path'])) die ('No payment possible because I don\'t know how to handle it!');
		
		require_once($config['path']);
		$paymentObj = t3lib_div::makeInstance($config['class']);
		
		
		
		if (
			$paymentObj->needAdditionalData() && (
				(isset($this->MYSESSION['payment']) && !$paymentObj->proofData($this->MYSESSION['payment'])) ||
				(!isset($this->MYSESSION['payment']))
				)
			) {
				// merge local lang array
				if (is_array($this->LOCAL_LANG) && isset($paymentObj->LOCAL_LANG)) {
					foreach ($this->LOCAL_LANG as $llKey => $llData) {
						$newLLData = array_merge($llData, $paymentObj->LOCAL_LANG[$llKey]);
						$this->LOCAL_LANG[$llKey] = $newLLData;
					}
				}
				
				// show the payment form if it's needed
				$paymentForm = '<form name="paymentForm" action="" method="post">';
				$paymentForm .= '<input type="hidden" name="'.$this->prefixId.'[step]" value="listing" />';
					
				$paymentConfig = $this->conf['payment.'];
				$paymentConfig['sourceFields.'] = $paymentObj->getAdditonalFieldsConfig();
				$paymentForm .= $this->getInputForm($paymentConfig, 'payment', false);
				
				$markerArray['###PAYMENT_FORM_FIELDS###'] = $paymentForm;
				$markerArray['###PAYMENT_FORM_SUBMIT###'] = '<input type="submit" value="' .$this->pi_getLL('payment_submit') .'" /></form>';
		} else {
			// redirect to the next page because no additonal payment information are needed or if anything is correct
			return false;
		}
		/**
		 * Hook for processing Marker Array
		 * Inspired by tt_news
		 * @since 21.01.2006
		 * 
		 */
		$hookObjectsArr = array();
		if (is_array ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['commerce/pi5/class.tx_commerce_pi5.php']['handlePayment'])) {
			foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['commerce/pi5/class.tx_commerce_pi5.php']['handlePayment'] as $classRef) {
					$hookObjectsArr[] = &t3lib_div::getUserObj($classRef);
			}
		}
		foreach($hookObjectsArr as $hookObj)	{
			if (method_exists($hookObj, 'ProcessMarker')) {
				$markerArray=$hookObj->ProcessMarker($markerArray,$this);
			}
		}
		return $this->cObj->substituteMarkerArray($template, $markerArray);
		
	}
	
	/**
	 * Method to list the content of the basket including all articles, sums and addresses.
	 * @param Template for rendering
	 */
	function getListing($template=false) {
		
		if (!$template)
		{
			$template = $this->cObj->getSubpart($this->templateCode, '###LISTING###');
			
		}
		#debug($GLOBALS['TSFE']->fe_user->tx_commerce_basket);
		$listingForm = '<form name="listingForm" action="" method="post">';
		$listingForm .= '<input type="hidden" name="'.$this->prefixId.'[step]" value="finish" />';
		
		$markerArray['###LISTING_TITLE###'] = $this->pi_getLL('listing_title');
		$markerArray['###LISTING_DESCRIPTION###'] = $this->pi_getLL('listing_description');
		$markerArray['###LISTING_FORM_FIELDS###'] = $listingForm;
		
		$markerArray['###LISTING_BASKET###'] = $this->makeBasketView(
								$GLOBALS['TSFE']->fe_user->tx_commerce_basket,
								'###BASKET_VIEW###',
								array(NORMALArticleType));
	
	#	$markerArray['###LISTING_BASKET_GENERAL###'] = $this->getBasketSum();
		
		$markerArray['###BILLING_ADDRESS###'] = $this->getAddress('billing');
		$markerArray['###DELIVERY_ADDRESS###'] = $this->getAddress('delivery');
		
		$markerArray['###LISTING_FORM_SUBMIT###'] = '<input type="submit" value="' .$this->pi_getLL('listing_submit') .'" /></form>';
		$markerArray['###LISTING_DISCLAIMER###'] = $this->pi_getLL('listing_disclaimer');
		
	
		
		if ($this->formError['terms'])
		{
			
			$markerArray['###ERROR_TERMS_ACCEPT###'] = $this->cObj->dataWrap($this->formError['terms'],$this->conf['terms.']['errorWrap']);
		}
		else
		{
			$markerArray['###ERROR_TERMS_ACCEPT###'] = '';
		}
		
		if ($this->conf['termsdefaultchecked'])
		{
			$termeschekd='checked';
		}
		/**
		 * @TODO TS Coding with Sacha
		 */
		$markerArray['###LISTING_TERMS_ACCEPT###'] = $this->pi_getLL('termestext').'<input type="checkbox" name="'.$this->prefixId.'[terms]" value="termschecked" '.$termeschekd.' />';
		$markerArray['###LISTING_COMMENT###'] = $this->pi_getLL('comment').
			
			'<br/><textarea name="'.$this->prefixId.'[comment]" rows="4" cols="40"></textarea>';
		/**
		 * Hook for processing Marker Array
		 * Inspired by tt_news
		 * @since 21.01.2006
		 * 
		 */
		$hookObjectsArr = array();
		if (is_array ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['commerce/pi5/class.tx_commerce_pi5.php']['getListing'])) {
			foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['commerce/pi5/class.tx_commerce_pi5.php']['getListing'] as $classRef) {
					$hookObjectsArr[] = &t3lib_div::getUserObj($classRef);
			}
		}
		foreach($hookObjectsArr as $hookObj)	{
			if (method_exists($hookObj, 'ProcessMarker')) {
				$markerArray=$hookObj->ProcessMarker($markerArray,$this);
			}
		}
		return $this->cObj->substituteMarkerArray($template, $markerArray);
	}
	
	/**
	 * Finishing Page from Checkout
	 * @return	string	HTML-Content
	 */
	
	function finishIt() {
		
		$sysConfig = $GLOBALS['TYPO3_CONF_VARS']['EXTCONF'][$this->extKey]['SYSPRODUCTS']['PAYMENT'];
		$paymentType = $this->getPaymentType();
		$config = $sysConfig['types'][strtolower((string)$paymentType)];
		if (!isset($config['class']) || !file_exists($config['path'])) die ('No payment possible because I don\'t know how to handle it!');
			require_once($config['path']);
			$paymentObj = t3lib_div::makeInstance($config['class']);
		
			if (method_exists($paymentObj, 'checkExternalData')) {
			    	$paymentDone = $paymentObj->checkExternalData($_REQUEST, $this->MYSESSION);
			} else {
				$paymentDone = false;
			}
		
		// check if Terms are acceptes
		if (!$paymentDone && (empty($this->piVars['terms']) || ($this->piVars['terms'] != 'termschecked'))) {
			
			$this->formError['terms']=$this->pi_getLL('error_terms_not_accepted');
			$content=$this->handlePayment();
			if ($content == false)	{
				$this->formError['terms']=$this->pi_getLL('error_terms_not_accepted');
				$content = $this->getListing();
			}
			return $content;
		}
		

		
		// first of all, call the finish method from the payment class
	
		$sysConfig = $GLOBALS['TYPO3_CONF_VARS']['EXTCONF'][$this->extKey]['SYSPRODUCTS']['PAYMENT'];
		
		$hookObjectsArr = array();
		if (is_array ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['commerce/pi5/class.tx_commerce_pi5.php']['finishIt'])) {
				foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['commerce/pi5/class.tx_commerce_pi5.php']['finishIt'] as $classRef) {
						$hookObjectsArr[] = &t3lib_div::getUserObj($classRef);
				}
		}
			
		// handle the orders
		// &tx_commerce_pi1[artAddUid][2]=2&tx_commerce_pi1[artAddUid][1]=5
		$basket = $GLOBALS['TSFE']->fe_user->tx_commerce_basket;
		# debug($basket);
		
		// merge local lang array
		if (is_array($this->LOCAL_LANG) && isset($paymentObj->LOCAL_LANG)) {
			foreach ($this->LOCAL_LANG as $llKey => $llData) {
				$newLLData = array_merge($llData, $paymentObj->LOCAL_LANG[$llKey]);
				$this->LOCAL_LANG[$llKey] = $newLLData;
			}
		}
		$paymentObj->parentObj = $this;
		if (method_exists($paymentObj, 'hasSpecialFinishingForm') && $paymentObj->hasSpecialFinishingForm($_REQUEST)) {
			$content = $paymentObj->getSpecialFinishingForm($config, $this->MYSESSION, $basket);
			return $content;
		} else {
			if (!$paymentObj->finishingFunction($config, $this->MYSESSION, $basket)) {
				$content = $paymentObj->getLastError(1);
				$content .= $this->handlePayment();
				return $content;
			}
		}
		
		foreach($hookObjectsArr as $hookObj)	{
			if (method_exists($hookObj, 'postpayment')) {
				$hookObj->postpayment($paymentObj,$basket,$this);
			}
		}
	
		
		/**
		 * Real finishing starts here !
		 */
		// save addresses
		// get address types
		$uids = array();
		$res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('name', 'tx_commerce_address_types', '1');
		while ($type = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
			$uids[$type['name']] = $this->handleAddress($type['name']);
		}
		
		$orderData = array();
		$orderData['cust_deliveryaddress'] = ((isset($uids['delivery'])) ? $uids['delivery'] : $uids['billing']);
		// ############## THIS HAS TO BE UNIQUE IN ANOTHER WAY!!! #########
		$now = time();
		
		/*
		 * Hook for generating The OrderId
		 */
		
		foreach($hookObjectsArr as $hookObj)	{
			if (method_exists($hookObj, 'generateOrderId')) {
				
				$orderId = $hookObj->generateOrderId($orderId,$basket,$this);
				}
		
		}
		
		if (empty($orderId))
		{
			$orderId= uniqid('',true);
			/**
			 * @see http://www.php.net/uniqid
			 */
		}
		
		$this->orderId=$orderId;
		
		$orderData['order_id'] = $orderId;
		if (is_array($GLOBALS['TSFE']->fe_user->user)) {
			$orderData['cust_fe_user'] = $GLOBALS['TSFE']->fe_user->user['uid'];
		}
		$orderData['cust_invoice'] = $uids['billing'];
		$orderData['paymenttype'] = $this->getPaymentType();
		$orderData['sum_price_net'] = $basket->get_net_sum();
		$orderData['sum_price_gross'] = $basket->get_gross_sum();
		$comPid = array_keys(tx_graytree_folder_db::getFolders('commerce', 0, 'COMMERCE'));
		$ordPid = array_keys(tx_graytree_folder_db::getFolders('commerce', $comPid[0], 'Orders'));
		$incPid = array_keys(tx_graytree_folder_db::getFolders('commerce', $ordPid[0], 'Incoming'));
		$orderData['pid'] = $incPid[0];
		$orderData['crdate'] = $now;
		$orderData['tstamp'] = $now;
		
		$orderData['comment'] = $this->piVars['comment'];
		
			
		// insert order
		
		foreach($hookObjectsArr as $hookObj)	{
			if (method_exists($hookObj, 'preinsert')) {
				$hookObj->preinsert($orderData,$this);
			}
		}
		
		$GLOBALS['TYPO3_DB']->exec_INSERTquery('tx_commerce_orders', $orderData);
		$orderUid = $GLOBALS['TYPO3_DB']->sql_insert_id();
		// make orderUid avaible in hookObjects
		$this->orderUid = $orderUid;
		// call the update method from the payment class
 		$paymentObj->updateOrder($orderUid, $this->MYSESSION);
		
		// save order articles
		if (is_array($basket->basket_items)) {
			foreach ($basket->basket_items as $artUid => $basketItem) {
				// debug($basketItem->article);
				$oaData = array();
				$oaData['pid'] = $incPid[0];
				$oaData['crdate'] = $now;
				$oaData['tstamp'] = $now;
				$oaData['article_uid'] = $artUid;
				$oaData['article_type_uid'] = $basketItem->getArticleTypeUid();
				$oaData['article_number'] = $basketItem->getOrdernumber();
				$oaData['title'] = $basketItem->getTitle();
				$oaData['subtitle'] = $basketItem->getSubtitle();
				$oaData['price_net'] = $basketItem->get_price_net();
				$oaData['price_gross'] = $basketItem->get_price_gross();
				$oaData['tax'] = $basketItem->get_tax();
				$oaData['amount'] = $basketItem->get_quantity();
				$oaData['order_uid'] = $orderUid;
				$oaData['order_id'] = $orderId;
				
		#		debug($oaData);
				// insert
				$GLOBALS['TYPO3_DB']->exec_INSERTquery('tx_commerce_order_articles', $oaData);
			}
		}
		
		
		/**
		 * Send the emails
		 */
		$this->sendUserMail($orderId,$orderData);
		$this->sendAdminMail($orderId,$orderData);
		
		/**
		 * Do the output
		 */
		$content = $this->cObj->getSubpart($this->templateCode, '###FINISH###');
		$markerArray['###LISTING_BASKET###'] = $this->makeBasketView(
								$GLOBALS['TSFE']->fe_user->tx_commerce_basket,
								'###BASKET_VIEW###',
								array(NORMALArticleType));
		
		$markerArray['###MESSAGE###']='';
		
		$markerArray['###LISTING_TITLE###'] = $this->pi_getLL('order_confirmation');
		
		
		if ($orderData['cust_deliveryaddress'])	{
			$res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', 'tt_address', 'uid='.$orderData['cust_deliveryaddress']);
			if ($data= $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res))	{
				$deliveryAdress = $this->makeAdressView($data,'###DELIVERY_ADDRESS###');
			}
		}
		$content = $this->cObj->substituteSubpart($content,'###DELIVERY_ADDRESS###',$deliveryAdress);
		
		$billingAdress = '';
		if ($orderData['cust_invoice'])	{
			$res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', 'tt_address', 'uid='.$orderData['cust_deliveryaddress']);
			if ($data= $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res))	{
				$billingAdress = $this->makeAdressView($data,'###BILLING_ADDRESS###');
				$markerArray['###CUST_NAME###']=$data['NAME'];
			}
		}
		$content = $this->cObj->substituteSubpart($content,'###BILLING_ADDRESS###',$deliveryAdress);
		
		foreach($hookObjectsArr as $hookObj)	{
			if (method_exists($hookObj, 'ProcessMarker')) {
				$markerArray=$hookObj->ProcessMarker($markerArray,$this);
			}
		}
		
		$content = $this->cObj->substituteMarkerArray($content, $markerArray);
		
		foreach($hookObjectsArr as $hookObj)	{
			if (method_exists($hookObj, 'postFinish'))	{
					$hookObj->postFinish($basket,$this);
				}
		}
		
		// at last remove some things from the session
		unset($this->MYSESSION['billing']);
		unset($this->MYSESSION['delivery']);
		unset($this->MYSESSION['payment']);
		
		$GLOBALS['TSFE']->fe_user->tx_commerce_basket->finishOrder();
		return $content;
	}

	/** HELPER ROUTINES **/
	
	/**
	 * This method returns an general overview about the basket content.
	 * It contains 
	 *  - price for all articles (sum net)
	 *  - the price for shipping and package
	 *  - the netto sum
	 *  - the sum for tax
	 *  - the end sum (gross)
	 *
	 * @return	String with basket sum
	 */
	function getBasketSum($type = 'WEB') {
		$basket = $GLOBALS['TSFE']->fe_user->tx_commerce_basket;
		$sumNet = 0;
		$sumGross = 0;
		$sumTax = 0;
		$sumShipping = 0;
		
		$template = $this->cObj->getSubpart($this->templateCode, '###LISTING_BASKET_' .strtoupper($type) . '###');
		
		$sumNet = $basket->get_net_sum();
		$sumGross = $basket->get_gross_sum();
		
		$sumTax = $sumGross - $sumNet;
		$delivery_article_array=$basket->get_articles_by_article_type_uid_asUidlist(DELIVERYArticleType);
		$sumShippingNet=0;
		$sumShippingGross=0;
		foreach ($delivery_article_array as $oneDeliveryArticle)
		{
			$sumShippingNet+=$basket->basket_items[$oneDeliveryArticle]->get_price_net();	
			$sumShippingGross+=$basket->basket_items[$oneDeliveryArticle]->get_price_gross();
			
		}
		$payment_article_array=$basket->get_articles_by_article_type_uid_asUidlist(PAYMENTArticleType);
		
		$sumPaymentNet=0;
		$sumPaymentGross=0;
		foreach ($payment_article_array as $onePaymentArticle)
		{
			$sumPaymentNet+=$basket->basket_items[$onePaymentArticle]->get_price_net();	
			$sumPaymentGross+=$basket->basket_items[$onePaymentArticle]->get_price_gross();
			
		}
		$paymentTitle=$basket->getFirstArticleTypeTitle(PAYMENTArticleType);
		
		
		#
		#$sumShipping_net = $basket->basket_items[$this->basketDel]->get_price_net();
		
		#$sumShipping_gross = $delivery_article->get_price_gross();
		
		$markerArray = array();
		$markerArray['###LABEL_SUM_ARTICLE_NET###'] = $this->pi_getLL('listing_article_net');
		$markerArray['###LABEL_SUM_ARTICLE_GROSS###'] = $this->pi_getLL('listing_article_gross');
		$markerArray['###SUM_ARTICLE_NET###'] = tx_moneylib::format($sumNet,$this->currency);
		$markerArray['###SUM_ARTICLE_GROSS###'] = tx_moneylib::format($sumGross,$this->currency);
		$markerArray['###LABEL_SUM_SHIPPING_NET###'] = $this->pi_getLL('listing_shipping_net');
		$markerArray['###LABEL_SUM_SHIPPING_GROSS##'] = $this->pi_getLL('listing_shipping_gross');
		$markerArray['###SUM_SHIPPING_NET###'] = tx_moneylib::format($sumShippingNet,$this->currency);
		$markerArray['###SUM_SHIPPING_GROSS###'] = tx_moneylib::format($sumShippingGross,$this->currency);
		$markerArray['###LABEL_SUM_NET###'] = $this->pi_getLL('listing_sum_net');
		$markerArray['###SUM_NET###'] = tx_moneylib::format(($sumNet + $sumShipping),$this->currency);
		$markerArray['###LABEL_SUM_TAX###'] = $this->pi_getLL('listing_tax');
		$markerArray['###SUM_TAX###'] = tx_moneylib::format(intval($sumTax),$this->currency);;
		$markerArray['###LABEL_SUM_GROSS###']= $this->pi_getLL('listing_sum_gross');
		$markerArray['###SUM_GROSS###'] = tx_moneylib::format(intval($sumGross),$this->currency);
		$markerArray['###SUM_PAYMENT_NET###'] = tx_moneylib::format(intval($sumPaymentNet),$this->currency);
		$markerArray['###SUM_PAYMENT_GROSS###'] = tx_moneylib::format(intval($sumPaymentGross),$this->currency);
		$markerArray['###PAYMENT_TITLE###'] = $paymentTitle;
		
		/**
		 * Hook for processing Marker Array
		 * Inspired by tt_news
		 * @since 21.01.2006
		 * 
		 */
		$hookObjectsArr = array();
		if (is_array ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['commerce/pi5/class.tx_commerce_pi5.php']['getBasketSum'])) {
			foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['commerce/pi5/class.tx_commerce_pi5.php']['getBasketSum'] as $classRef) {
					$hookObjectsArr[] = &t3lib_div::getUserObj($classRef);
			}
		}
		foreach($hookObjectsArr as $hookObj)	{
			if (method_exists($hookObj, 'ProcessMarker')) {
				$markerArray=$hookObj->ProcessMarker($markerArray,$this);
			}
		}
		return $this->cObj->substituteMarkerArray($template, $markerArray);
	}
	
	/**
	 * Returns a string that contains the address data of the specified type.
	 * The type can be 'billing' or 'delivery'.
	 *
	 * @param	string	$addressType: The type of the address that should be exported from the session
	 * @param	string	$newLine: The string that is used a splitter between the single lines
	 * @return	String with address
	 */
	function getAddress($addressType, $newLine = '<br />',$headstart = '<strong>',$headstop='</strong>') {
		// $typeUpper = strtoupper($addressType);
		$typeLower = strtolower($addressType);

		
		if (is_array($this->MYSESSION[$typeLower]) && (count($this->MYSESSION[$typeLower]) > 0)) {
			$addressArray = array($headstart .$this->pi_getLL($addressType.'_title'). $headstop. $newLine,
				$this->MYSESSION[$typeLower]['name'],
				$this->MYSESSION[$typeLower]['surname'],
				$this->MYSESSION[$typeLower]['address'],
				$this->MYSESSION[$typeLower]['zip'],
				$this->MYSESSION[$typeLower]['city'],
				$this->MYSESSION[$typeLower]['email'],
				$this->MYSESSION[$typeLower]['telephone'],
				$this->MYSESSION[$typeLower]['company']
			);
			return implode($newLine, $addressArray);
		} else {
			return '';
		}
	}

	/**
	 * Checks if an address in the SESSION is valid
	 *
	 */
	function validateAddress($addressType) {
		$typeLower = strtolower($addressType);
		$config = $this->conf[$typeLower .'.'];
		$this->formError = array();
		
		if ($this->piVars['check'] != $addressType) return true;

		// if the address doesn't exsist in the session it's valid. For the case that
		// not delivery address was set
		$isArray = is_array($this->MYSESSION[$typeLower]);
		if (!$isArray && $typeLower == 'delivery') return true;
		if (!$isArray && $typeLower != 'delivery') return false;

#debug($this->MYSESSION[$typeLower]);
#debug($config);
		foreach ($this->MYSESSION[$typeLower] as $name => $value) {
#		debug($config['sourceFields.'][$name .'.'],$name);
			if ($config['sourceFields.'][$name .'.']['mandatory'] == 1 && strlen($value) == 0) {
				$this->formError[$name] = $this->pi_getLL('error_field_mandatory');
				return false;
				
			}
			$eval = explode(',', $config[$name .'.']['eval']);
			foreach ($eval as $method) {
				$method = explode('_', $method);
				switch (strtolower($method[0]))	{
					case 'email':
						if (!t3lib_div::validEmail($value)) {
							$this->formError[$name] = $this->pi_getLL('error_field_email');
							return false;
						}
						break;
					case 'string':
						if (!is_string($value)) {
							$this->formError[$name] = $this->pi_getLL('error_field_string');
							return false;
						}
						break;
					case 'int':
						if (!is_integer($value)) {
							$this->formError[$name] = $this->pi_getLL('error_field_int');
							return false;
						}
						break;
					case 'min':
						if (strlen((string)$value) < intval($method[1])) {
							$this->formError[$name] = $this->pi_getLL('error_field_min');
							return false;
						}
						break;
					case 'max':
						if (strlen((string)$value) > intval($method[1])) {
							$this->formError[$name] = $this->pi_getLL('error_field_max');
							return false;
						}
						break;
					case 'alpha':
						if (preg_match('/[0-9]/', $value) === 1) {
							$this->formError[$name] = $this->pi_getLL('error_field_alpha');
							return false;
						}
						break;
				}
			}
		}
		
		return true;
	}
	
	function getPaymentData() {
		$result = '';
		if (is_array($this->MYSESSION['mails']['payment'])) {
			foreach ($this->MYSESSION['mails']['payment'] as $k => $data) {
				if (k <> 'cc_checksum') {
					$result .= $data['label'] .' : ';
					if ($k == 'cc_number') {
						$data['data'] = substr($data['data'], 0, -3) .'XXX';
					}
					$result .= $data['data'] ."\n";
				}
			}
		}
		return $result;
	}
	
	/**
	 * Returns the payment type. The type is extracted from the basket object. The type
	 * is stored in the basket as a special article.
	 *
	 * @return	A string that determines the payment type ('creditcard', 'invoice' or whatever
	 */
	function getPaymentType() {
		
		$basket = $GLOBALS['TSFE']->fe_user->tx_commerce_basket;
		$payment = $basket->get_articles_by_article_type_uid_asuidlist(PAYMENTArticleType);
		#debug($basket->basket_items[$payment[0]]->article);
		$paymenttitle = $basket->basket_items[$payment[0]]->article->classname;
		return strtolower($paymenttitle);
	}
	
	
	/**
	 * Creates a form from a table where the fields can prefilled, configured
	 * via TypoScript.
	 */
	function getInputForm($config, $step, $parseList = true) {
		// build a query for selecting an address from the database if we have a logged in user

		if ($parseList) {
			$fieldList = $this->parseFieldList($config['sourceFields.']);
		} else {
			$fieldList = array_keys($config['sourceFields.']);
		}
 	
		
		$this->dbFieldData = $this->getAddressFromDB($config, $step, $fieldList);
		
		$fieldTemplate = $this->cObj->getSubpart($this->templateCode, '###SINGLE_INPUT###');
		$fieldCode = '';
		
		foreach ($fieldList as $fieldName) {
			$fieldMarkerArray = array();
			
			$fieldLabel = $this->pi_getLL($step .'_' .$fieldName, $this->pi_getLL('general_' .$fieldName));
			
			if ($config['sourceFields.'][$fieldName .'.']['mandatory'] == '1') {
				
				$fieldLabel .= ' ' .$this->cObj->stdWrap($config['mandatorySign'],$config['mandatorySignStdWrap.']);
			}
			
			$fieldMarkerArray['###FIELD_LABEL###'] = $fieldLabel;
			
			// clear the error field, this has to be implemented in future versions
			if (strlen($this->formError[$fieldName]) > 0) {
				$fieldMarkerArray['###FIELD_ERROR###'] = $this->formError[$fieldName];
			} else {
				$fieldMarkerArray['###FIELD_ERROR###'] = '';
			}
			
			// create input field
			// In this version we only create some simple text fields.
			$arrayName = $fieldName .(($parseList) ? '.' : '');
			#debug($config['sourceFields.'][$arrayName],$fieldName);
			$fieldMarkerArray['###FIELD_INPUT###'] = $this->getInputField($fieldName, $config['sourceFields.'][$arrayName], $step);
			$fieldMarkerArray['###FIELD_NAME###'] = $this->prefixId.'['.$step.'][' .$fieldName .']';
			
			// save some data for mails
			$this->MYSESSION['mails'][$step][$fieldName] = array('data' => $this->MYSESSION[$step][$fieldName], 'label' => $fieldLabel);
			
			$fieldCode .= $this->cObj->substituteMarkerArray($fieldTemplate, $fieldMarkerArray);
		}
		$GLOBALS['TSFE']->fe_user->setKey('ses','mails', $this->MYSESSION['mails']);
		
		return $fieldCode;
	}
	
	function getAddressFromDB($config, $step, $fieldList = array(), $getFromSession = true) {
		$dbFieldData = false;
		if ($getFromSession && isset($this->MYSESSION[$step])) {
			return $this->MYSESSION[$step];
		}
		
		if (is_array($GLOBALS['TSFE']->fe_user->user) && 
			isset($config['userConnection']) &&
			isset($config['sourceLimiter.'])
			
			) {
			$where = $config['userConnection'] .'=' .$GLOBALS['TSFE']->fe_user->user['uid'];
			$where .= ' AND ' .$config['sourceLimiter.']['field'] .'=\'' .$config['sourceLimiter.']['value'] .'\'';
			$where .= t3lib_befunc::BEenableFields('tt_address');
			$where .= ' AND deleted=0';
			
			// get the data. Order by uid descending to make sure that we get the most recent entry even if there
			// are more available in the database
			if (count($fieldList) > 0) {
				$select = implode(',', $fieldList) .',uid';
			} else {
				$select = 'uid';
			}
			
			$res = $GLOBALS['TYPO3_DB']->exec_SELECTquery($select, $config['sourceTable'], $where, '', 'uid DESC', '1');
			$dbFieldData = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res);
		}
		
		return $dbFieldData;
	}
	
		
	function handleAddress($type) {
		if (!is_array($this->MYSESSION[$type])) return;
		
		$config = $this->conf[$type .'.'];
		$dbData = $this->getAddressFromDB($config, $type, array(), false);
		$fieldList = $this->parseFieldList($config['sourceFields.']);
		
		if (is_array($fieldList)) {
			foreach ($fieldList as $fieldName) {
				$dataArray[$fieldName] = $this->MYSESSION[$type][$fieldName];
			}
		}
		
		if (is_array($dbData)) {
			$uid = $dbData['uid'];
			$where = 'uid=' .$dbData['uid'];
		
			// update
			$GLOBALS['TYPO3_DB']->exec_UPDATEquery(
				'tt_address',
				$where,
				$dataArray
			);
		} else {
			// create
			if (isset($this->conf['addressFolder']))	{
				$dataArray['pid'] = $this->conf['addressFolder'];
			} else {
				list($commercePid, $defaultFolder, $folderList) = tx_graytree_folder_db::initFolders('Commerce', 'commerce', $modPid);
				$dataArray['pid'] = $commercePid;
			}
			
			if (isset($GLOBALS['TSFE']->fe_user->user['uid']))	{
				$dataArray[$config['userConnection']] = $GLOBALS['TSFE']->fe_user->user['uid'];
			} else {
				// create a new user if no user is logged in and the option is set
				if ($this->conf['createNewUsers']){
					$feuData = array();
					$feuData['pid'] = $this->conf['userFolder'];
					$feuData['tstamp'] = time();
					$feuData['username'] = substr($this->MYSESSION[$type]['name'], 0, 2) .substr($this->MYSESSION[$type]['surname'], 0, 4) .substr(uniqid(rand()), 0, 4);
					$feuData['password'] = substr(uniqid(rand()), 0, 6);
					$feuData['email'] = $this->MYSESSION['email'];
					$GLOBALS['TYPO3_DB']->exec_INSERTquery('fe_users', $feuData);
					$dataArray[$config['userConnection']] = $GLOBALS['TYPO3_DB']->sql_insert_id();
					$GLOBALS['TSFE']->fe_user->user['uid'] = $dataArray[$config['userConnection']];
				}
			}
			$dataArray[$config['sourceLimiter.']['field']] = $config['sourceLimiter.']['value'];
			
			
			$GLOBALS['TYPO3_DB']->exec_INSERTquery(
				'tt_address',
				$dataArray
			);
			$uid = $GLOBALS['TYPO3_DB']->sql_insert_id();
		}
		
		return $uid;
	}
	
	/**
	 * Returns a single input form field.
	 */
	function getInputField($fieldName, $fieldConfig, $step) {
		switch (strtolower($fieldConfig['type'])) {
			case 'select':
				return $this->getSelectInputField($fieldName, $fieldConfig, $step);
			case 'single':
			default:
				return $this->getSingleInputField($fieldName, $fieldConfig, $step);
		}
	}
	
	/**
	 * Returns a single textfield
	 */
	function getSingleInputField($fieldName, $fieldConfig, $step) {
		
		if (($fieldConfig['default']) && empty($this->dbFieldData[$fieldName]))
		{
			$value=$fieldConfig['default'];
		}
		else
		{
			$value=$this->dbFieldData[$fieldName];
		}
		
		$result = '<input type="text" name="'.$this->prefixId.'['.$step.'][' .$fieldName .']" value="' .$value .'" ';
		if ($fieldConfig['readonly']==1)
		{
			$result.=' readonly disabled';	
		}
		$result .='/>';
		return $result;
	}
	
	/**
	 * Returns a selectbox
	 */
	function getSelectInputField($fieldName, $fieldConfig, $step) {
		$result .= '<select name="'.$this->prefixId.'[' .$step .'][' .$fieldName .']">';
		if (is_array($fieldConfig['values'])) {
			foreach ($fieldConfig['values'] as $option) {
				$result .= '<option name="' .$option .'" value="' .$option .'">' .$option .'</option>';
			}
		}
		$result .= '</select>';
		return $result;
	}
	
	/**
	 * Creates a list of array keys where the last character is removed from it.
	 *
	 */
	function parseFieldList($fieldConfig) {
		$result = array();
		if (!is_array($fieldConfig)) return $result;
		
		foreach ($fieldConfig as $key => $data) {
			// remove the trailing '.'
			$result[] = substr($key, 0, -1);
		}
		
		return $result;
	}
	
	/**
	 * Returns wether a checkout is allowed or not.
	 * Currently it always returns TRUE!!!
	 *
	 * @TODO implement some checks
	 */
	function canMakeCheckout() {
		return true;
	}
	
	/**
	 * Sends the Information Mail to the user
	 * @since 12th November 2005
	 * Also performes a charset Conversion for the mail
	 * @param Order ID
	 * @param Order Data
	 * @retunr returns true if success
	 */
	function sendUserMail($orderUid, $orderData){
		
		$hookObjectsArr = array();
		if (is_array ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['commerce/pi5/class.tx_commerce_pi5.php']['sendUserMail'])) {
			foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['commerce/pi5/class.tx_commerce_pi5.php']['sendUserMail'] as $classRef) {
						$hookObjectsArr[] = &t3lib_div::getUserObj($classRef);
			}
		}
		
		if (is_array($GLOBALS['TSFE']->fe_user->user&&strlen($GLOBALS['TSFE']->fe_user->user['email']))) {
			$userMail = $GLOBALS['TSFE']->fe_user->user['email'];
		} else {
		 	$userMail = $this->MYSESSION['billing']['email'];
		}
		/**
		 * Check for no injection codes
		 * 
		 */
		if (strstr($userMail, '@') && !eregi("\r",$userMail) && !eregi("\n",$userMail)) {
		 	
			foreach($hookObjectsArr as $hookObj)	{
				if (method_exists($hookObj, 'getUserMail')) {
					$hookObj->getUserMail($userMail,$orderUid,$orderData,$this);
					}
			}
			if ($userMail != '' && $this->cObj->checkEmail($userMail)) {
				$UserMailObj=t3lib_div::makeInstance('tx_commerce_pi5');
				$UserMailObj->conf = $this->conf;
				$UserMailObj->pi_setPiVarDefaults();
				$UserMailObj->cObj=$this->cObj;
				$UserMailObj->pi_loadLL();
				$UserMailObj->currency = $this->currency;
				$UserMailObj->showCurrency = false;
				$UserMailObj->templateCode=$this->cObj->fileResource($this->conf['UserMailTemplateFile']);
				
				foreach($hookObjectsArr as $hookObj)	{
					if (method_exists($hookObj, 'preGenerateMail')) {
					$hookObj->preGenerateMail($UserMailObj,$this);
					}
				}
				
				$mailcontent=$UserMailObj->generateMail($orderUid, $orderData);
				
				foreach($hookObjectsArr as $hookObj)	{
					if (method_exists($hookObj, 'PostGenerateMail')) {
						$hookObj->PostGenerateMail($UserMailObj,$this,$GLOBALS['TSFE']->fe_user->tx_commerce_basket,$mailcontent,$this);
					}
				}
				
				/**
				 * @since 2005 12th November
				 * Noved to plainMailEncoded
				 */
				$parts = split(chr(10),$mailcontent,2);		// First line is subject
				$subject=trim($parts[0]);
				$plain_message=trim($parts[1]);
				
				$headers=array();
				$headers[]='From: '.$this->conf['usermail.']['from_name'].' <'.$this->conf['usermail.']['from'].'>';
				$headers[]='Reply-To: '.$this->conf['usermail.']['from'];
				
				/**
				 * Check if charset ist set by TS
				 * Otherwise set to default Charset
				 * Checck if mailencoding ist set
				 * otherwise set to 8bit
				 */
				if (!$this->conf['usermail.']['charset'])
				{
					$this->conf['usermail.']['charset']=$GLOBALS['TSFE']->renderCharset;
				}
				if (!$this->conf['usermail.']['encoding '])
				{
				 	$this->conf['usermail.']['encoding ']='8bit';
				}
				/**
				 * Convert Text to charset
				 */
				$GLOBALS['TSFE']->csConvObj->initCharset($GLOBALS['TSFE']->renderCharset);
				$GLOBALS['TSFE']->csConvObj->initCharset(strtolower($this->conf['usermail.']['charset']));
				$plain_message=$GLOBALS['TSFE']->csConvObj->conv($plain_message,$GLOBALS['TSFE']->renderCharset,strtolower($this->conf['usermail.']['charset']));
				$subject=$GLOBALS['TSFE']->csConvObj->conv($subject,$GLOBALS['TSFE']->renderCharset,strtolower($this->conf['usermail.']['charset']));
				
				if ($this->debugMail==true)
				{
					print"<b>Usermail to $userMail</b><pre>$plain_message</pre>\n";	
				}
								
				return t3lib_div::plainMailEncoded($userMail, $subject, $plain_message, implode(chr(10),$headers),$this->conf['usermail.']['encoding '],$this->conf['usermail.']['charset']);
				
			}
		}
		return false;
		
		
	}
	
	/**
	 * Sends Admin Mail
	 * @since 12th November 2005
	 * Also performes a charset Conversion for the mail, including Sender
	 * @param Order ID
	 * @param Order Data
	 * @retunr returns true if success
	 */
	function sendAdminMail($orderUid, $orderData){
		$hookObjectsArr = array();
		if (is_array ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['commerce/pi5/class.tx_commerce_pi5.php']['sendAdminMail'])) {
			foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['commerce/pi5/class.tx_commerce_pi5.php']['sendAdminMail'] as $classRef) {
						$hookObjectsArr[] = &t3lib_div::getUserObj($classRef);
			}
		}
		if (is_array($GLOBALS['TSFE']->fe_user->user&&strlen($GLOBALS['TSFE']->fe_user->user['email']))) {
			$userMail = $GLOBALS['TSFE']->fe_user->user['email'];
		} else {
		 	$userMail = $this->MYSESSION['billing']['email'];
		}
		if (is_array($GLOBALS['TSFE']->fe_user->user&&strlen($GLOBALS['TSFE']->fe_user->user['email']))) {
			$userName = $GLOBALS['TSFE']->fe_user->user['name'].' '.$GLOBALS['TSFE']->fe_user->user['surname'];
		} else {
		 	$userName = $this->MYSESSION['billing']['name'].' '.$this->MYSESSION['billing']['surname'];
		}
		
	
		
		if ($this->conf['adminmail.']['from'] || $userMail)
		{
			$AdminMailObj=t3lib_div::makeInstance('tx_commerce_pi5');
			$AdminMailObj->conf = $this->conf;
			$AdminMailObj->pi_setPiVarDefaults();
			$AdminMailObj->cObj=$this->cObj;
			$AdminMailObj->pi_loadLL();
			
			$AdminMailObj->currency = $this->currency;
			$AdminMailObj->showCurrency = false;
			$AdminMailObj->templateCode=$this->cObj->fileResource($this->conf['AdminMailTemplateFile']);
		
			foreach($hookObjectsArr as $hookObj)	{
				if (method_exists($hookObj, 'preGenerateMail')) {
					$hookObj->preGenerateMail($AdminMailObj,$this);
				}
			}
			$mailcontent=$AdminMailObj->generateMail($orderUid, $orderData);
			
			foreach($hookObjectsArr as $hookObj)	{
				if (method_exists($hookObj, 'PostGenerateMail')) {
					$hookObj->PostGenerateMail($AdminMailObj,$this,$GLOBALS['TSFE']->fe_user->tx_commerce_basket,$mailcontent,$this);
				}
			}
		
			/**
			 * @since 2005 12th November
			 * Noved to plainMailEncoded
			 */
			$parts = split(chr(10),$mailcontent,2);		// First line is subject
			$subject=trim($parts[0]);
			$plain_message=trim($parts[1]);
			
			
			
						
			
			
			/**
			 * Check if charset ist set by TS
			 * Otherwise set to default Charset
			 * Checck if mailencoding ist set
			 * otherwise set to 8bit
			 */
			if (!$this->conf['adminmail.']['charset'])
			{
				$this->conf['adminmail.']['charset']=$GLOBALS['TSFE']->renderCharset;
			}
			if (!$this->conf['adminmail.']['encoding '])
			{
			 	$this->conf['adminmail.']['encoding ']='8bit';
			}
			/**
			 * Convert Text to charset
			 */
			$GLOBALS['TSFE']->csConvObj->initCharset($GLOBALS['TSFE']->renderCharset);
			$GLOBALS['TSFE']->csConvObj->initCharset(strtolower($this->conf['adminmail.']['charset']));
			$plain_message=$GLOBALS['TSFE']->csConvObj->conv($plain_message,$GLOBALS['TSFE']->renderCharset,strtolower($this->conf['adminmail.']['charset']));
			$subject=$GLOBALS['TSFE']->csConvObj->conv($subject,$GLOBALS['TSFE']->renderCharset,strtolower($this->conf['adminmail.']['charset']));
			$username_mailencoded=$GLOBALS['TSFE']->csConvObj->specCharsToASCII($GLOBALS['TSFE']->renderCharset,$userName);
			/**
			 * Check if user Mail is set
			 */
			$headers=array();
			if (($userMail) && ($userName))
			{
				$headers[]='From: '.$username_mailencoded.' <'.$userMail.'>';
				$headers[]='Reply-To: '.$userMail;
			}else
			{
				$headers[]='From: '.$this->conf['adminmail.']['from_name'].' <'.$this->conf['adminmail.']['from'].'>';
				$headers[]='Reply-To: '.$this->conf['adminmail.'];
			}
			
			if ($this->debugMail==true)
			{
				print"<b>Adminmail from </b><pre>$plain_message</pre>\n";	
			}
							
			return t3lib_div::plainMailEncoded($this->conf['adminmail.']['mailto'], $subject, $plain_message, implode(chr(10),$headers),$this->conf['adminmail.']['encoding '],$this->conf['adminmail.']['charset']);
						
			
			
		}
		
		return false;
		
		
	}
	
	/**
	 * Generates one Mail
	 * @param 	string	$orderUid	The Order UID
	 * @param	array	$orderData	Collected Order Data form PI3
	 * @return MailContent
	 */
	function generateMail($orderUid, $orderData)
	{
		$content='';
		$markeArray=array();
		#debug($orderData);
		$markerArray['###ORDERID###']=$orderUid;
		$markerArray['###COMMENT###']=$orderData['comment'];
	
		/**
		 * Since The first line of the mail is the Suibject, trim the template
		 */
		$template = ltrim($this->cObj->getSubpart($this->templateCode, '###MAILCONTENT###'));
		
		$basketContent = $this->makeBasketView(
								$GLOBALS['TSFE']->fe_user->tx_commerce_basket,
								'###BASKET_VIEW###',
								array(NORMALArticleType));
		
		$content = $this->cObj->substituteSubpart($template,'###BASKET_VIEW###',$basketContent);
		
		// Get The addresses
		$deliveryAdress='';
		if ($orderData['cust_deliveryaddress'])
		{
			$res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', 'tt_address', 'uid='.$orderData['cust_deliveryaddress']);
			if ($data= $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res))
			{
				$deliveryAdress = $this->makeAdressView($data,'###DELIVERY_ADDRESS###');
			}
			
		}
		$content = $this->cObj->substituteSubpart($content,'###DELIVERY_ADDRESS###',$deliveryAdress);
		
		$billingAdress='';
		if ($orderData['cust_invoice'])
		{
			$res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', 'tt_address', 'uid='.$orderData['cust_invoice']);
			if ($data= $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res))
			{
				$billingAdress = $this->makeAdressView($data,'###BILLING_ADDRESS###');
				$markerArray['###CUST_NAME###']=$data['NAME'];
			}
			
		}
		$content = $this->cObj->substituteSubpart($content,'###BILLING_ADDRESS###',$billingAdress);
		
		/**
		 * Hook for processing Marker Array
		 * Inspired by tt_news
		 * @since 21.01.2006
		 * 
		 */
		$hookObjectsArr = array();
		if (is_array ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['commerce/pi5/class.tx_commerce_pi5.php']['generateMail'])) {
			foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['commerce/pi5/class.tx_commerce_pi5.php']['generateMail'] as $classRef) {
					$hookObjectsArr[] = &t3lib_div::getUserObj($classRef);
			}
		}
		foreach($hookObjectsArr as $hookObj)	{
			if (method_exists($hookObj, 'ProcessMarker')) {
				$markerArray=$hookObj->ProcessMarker($markerArray,$this);
			}
		}
	 	$content = $this->cObj->substituteMarkerArray($content, $markerArray);
	
		return ltrim($content);
	}
}

if (defined('TYPO3_MODE') && $GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']["ext/commerce/pi5/class.tx_commerce_pi5.php"])	{
	include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']["ext/commerce/pi5/class.tx_commerce_pi5.php"]);
}